﻿using Alimentador.CustomControls;
using Alimentador.Foods;
using Alimentador.RightGroup.Patient;
using Alimentador.Validations;
using Microsoft.Win32;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Xml.Serialization;

namespace Alimentador
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        private const string AppName = "Plano Alimentar - IPS";
        /// <summary>
        /// PersonData file extension: ".RRB"
        /// </summary>
        public const string PERSON_DATA_FILE_EXTENSION = ".RRB";
        /// <summary>
        /// MenuData file extension: ".BRR"
        /// </summary>
        public const string MENU_DATA_FILE_EXTENSION = ".BRR";
        /// <summary>
        /// "Alimentos.xml"
        /// </summary>
        public const string NEW_FOOD_XML_FILENAME = "Alimentos";
        /// <summary>
        /// "Alimentos\\"
        /// </summary>
        //public const string FOODS_FOLDER = "Alimentos\\";
        /// <summary>
        /// "MyMenus\\"
        /// </summary>
        public const string MENUS_FOLDER = "MyMenus\\";

        /// <summary>
        /// Person Patient
        /// </summary>
        public static PersonPatient CurrentPatient = null;

        /// <summary>
        /// Deafult formula values
        /// </summary>
        public static DefaultValues Def = new DefaultValues();

        /// <summary>
        /// Store last opened file directory or application directory as MainWindow.Default.
        /// </summary>
        public static string SaveDirectory = "";

        /// <summary>
        /// Default directory to store profiles
        /// </summary>
        public static string ProfileDirectory = "";

        /// <summary>
        /// Default directory for saving custom menus
        /// </summary>
        public static string MenusDirectory = "";

        /// <summary>
        /// Food dictionary
        /// </summary>
        public List<MainCategoryList> m_mainFoodList;

        /// Added food list
        public static List<FoodBase> m_foodList = new List<FoodBase>();
        private System.Windows.Point m_startPoint = new System.Windows.Point();

        public string ALIMENTOS_PATH = "C:\\Program Files\\Alimentador\\Alimentos";
        public string DEFAULT_PATH = "C:\\Program Files\\Alimentador";

        /// <summary>
        /// Constructor
        /// </summary>
        public MainWindow()
        {
            InitializeComponent();

            MainWindow_CheckValidation();
            UnzipPackage();
            
            LoadDefaultFormulas();

            SetVersionNumber();
            SetFoodLists();
            InitializeEvents();
            
            ContextMenu theMenu = new ContextMenu();
            MenuItem LogoChangeItem = new MenuItem();
            LogoChangeItem.Header = "Escolher outro logotipo";
            LogoChangeItem.Click += LogoChangeItem_Click;
            theMenu.Items.Add(LogoChangeItem);

            PrintBtn.ContextMenu = theMenu;

            AppTitle_tb.Text = AppName; 
        }

        private void LoadDefaultFormulas()
        {
            try
            {
                string path = DEFAULT_PATH + "\\DefaultValues";
                XmlSerializer serializer = new XmlSerializer(Def.GetType());
                StreamReader reader = new StreamReader(path);
                Def = (DefaultValues)serializer.Deserialize(reader);
                reader.Close();
            }
            catch (Exception ex)
            {
                System.Console.WriteLine("Error loading default values: " + ex.Message);
                MessageBox.Show("Não foram carregados valores para as fórmulas.", "Aviso", MessageBoxButton.OK, MessageBoxImage.Error);

                this.Close();
                Environment.Exit(0);
            }
        }

        void LogoChangeItem_Click(object sender, RoutedEventArgs e)
        {
            MessageBox.Show("Escolha uma imagem. O tamanho aconselhado é de 92px por 62px e o máximo aconselhado é de 250px por 70px.", "Informação", MessageBoxButton.OK, MessageBoxImage.Information);

            OpenFileDialog SelectLogoFileDialog = new OpenFileDialog();

            SelectLogoFileDialog.Filter = "Files(*.PNG;*.BMP;*.JPG;*.GIF)|*.PNG;*.BMP;*.JPG;*.GIF";//"PNG|*.png|BMP|*.bmp|GIF|*.gif|JPG|*.jpg;*.jpeg";
            SelectLogoFileDialog.FilterIndex = 1;

            SelectLogoFileDialog.Multiselect = false;

            bool? userClickedOK = SelectLogoFileDialog.ShowDialog();

            if (userClickedOK == true)
            {
                // Open the selected file to read.
                string fileName = SelectLogoFileDialog.FileName;

                PDFHelper.PDFHelper.JpegLogoPath = fileName;

                PrintBtn_Click(sender, e);
            }
        }

        private int m_attempt = 0;

        private void MainWindow_CheckValidation()
        {
            Validator validator = new Validator();
            bool isValid = false;

            do
            {
                isValid = validator.CheckResponseCode();
                m_attempt++;
            }
            while (!isValid && m_attempt<4);
            
            if (!isValid)
            {
                WarningPopUp wpp = new WarningPopUp();
                wpp.YesBtn.Visibility = System.Windows.Visibility.Collapsed;
                wpp.Height = 250;
                wpp.Width = 450;
                wpp.NoBtn.Content = "OK";
                wpp.SetMessage = Validator.WARNING_MESSAGE;
                wpp.Title = "Aviso";
                wpp.NoBtn.Focus();
                wpp.ShowDialog();

                if (!wpp.PositiveSelection)
                {
                    this.Close();
                    Environment.Exit(0);
                }
            }
        }

        private void UnzipPackage()
        {
            string CurrentDirectory = Directory.GetCurrentDirectory() + "\\Extra";
            string CurrentDirectoryDef = Directory.GetCurrentDirectory() + "\\Extra\\DefaultValues";

            //string path = DEFAULT_PATH + "\\log.txt";
            //System.IO.File.WriteAllText(@path, "Begin" + Environment.NewLine);
            //System.IO.File.AppendAllText(@path, " CurrentDirectory :" + CurrentDirectory + Environment.NewLine);
            //System.IO.File.AppendAllText(@path, " CurrentDirectoryDef :" + CurrentDirectoryDef + Environment.NewLine);

            // D:\alimentador\Alimentador\Alimentador\Extra\DefaultValues.xml

            //ZipFile.CreateFromDirectory("C:\\Users\\ricardo araujo.VISIONBOX\\Dropbox\\Alimentador\\Alimentos", "c:\\Alimentos.zip", CompressionLevel.Fastest, false);

            bool currentExist = Directory.Exists(CurrentDirectory);
            //System.IO.File.AppendAllText(@path, "Exist:" + currentExist.ToString() + Environment.NewLine);
            if (currentExist)
            {
                //System.IO.File.AppendAllText(@path, "Exist currentExist" + Environment.NewLine);
                try
                {
                    //System.IO.File.AppendAllText(@path, "Not Exist ALIMENTOS_PATH" + (!Directory.Exists(ALIMENTOS_PATH)).ToString() + Environment.NewLine);
                    if (!Directory.Exists(ALIMENTOS_PATH))
                    {
                        Directory.CreateDirectory(ALIMENTOS_PATH);
                    }

                    if (!File.Exists(ALIMENTOS_PATH + "\\Alimentos"))
                    {
                        File.Copy(CurrentDirectory + "\\Alimentos", ALIMENTOS_PATH + "\\Alimentos");
                    }

                    if (!Directory.Exists(DEFAULT_PATH))
                    {
                        Directory.CreateDirectory(DEFAULT_PATH);
                    }

                    if (!File.Exists(DEFAULT_PATH + "\\DefaultValues"))
                    {
                        File.Copy(CurrentDirectoryDef, DEFAULT_PATH + "\\DefaultValues");
                    }
                }
                catch (Exception ex)
                {
                    MessageBox.Show(Directory.GetCurrentDirectory() + " " + ex.Message);
                }
            }
        }

        //ZipFile.ExtractToDirectory(CurrentDirectory+"Alimentos.xml", ALIMENTOS_PATH);
        //IEnumerable<string> ItemListPath = Directory.EnumerateDirectories(ALIMENTOS_PATH);
        //foreach (string str in ItemListPath) {
        //    if (str.IndexOf("¦") != -1) {
        //        if (Directory.Exists(str)) {
        //            Directory.Move(str, str.Replace("¦", "ã"));
        //        }
        //    }
        //    if (Directory.Exists(str)) {
        //        foreach (string str2 in Directory.EnumerateDirectories(str)) {
        //            if (str2.IndexOf("¦") != -1) {
        //                if (Directory.Exists(str2)) {
        //                    Directory.Move(str2, str2.Replace("¦", "ã"));
        //                }
        //            }
        //        }
        //    }
        //}

        /// <summary>
        /// Load food list, set treeview and week day controler.
        /// </summary>
        private void SetFoodLists()
        {
            m_mainFoodList = new List<MainCategoryList>();

            CheckDirectories();

            try
            {
                LoadFoodListFromFiles();
            }
            catch
            {
                MessageBox.Show("Não foram encontrados alimentos.", "Aviso", MessageBoxButton.OK, MessageBoxImage.Error);
            }

            if (!LoadFoodListToTreeView())
            {
                MessageBox.Show("Não foi possível carregar a lista de alimentos.", "Aviso", MessageBoxButton.OK, MessageBoxImage.Error);
            }

            SetTreeViewItems();

            WeekList_cb.SelectedIndex = 0;
            ShowHideWeekDays = false;
        }

        /// <summary>
        /// Set current aplication version on screen
        /// </summary>
        private void SetVersionNumber()
        {
            string versionVal = "";
            try
            {
                versionVal = System.Deployment.Application.ApplicationDeployment.CurrentDeployment.CurrentVersion.ToString();
            }
            catch
            {
                versionVal = System.Reflection.Assembly.GetExecutingAssembly().GetName().Version.ToString();
            }

            versionLbl.Content = "v" + versionVal;
        }

        /// <summary>
        /// Initialize events for the screen elements
        /// </summary>
        private void InitializeEvents()
        {
            this.Closing += MainWindow_Closing;

            FoodListTreeView.PreviewMouseLeftButtonDown += List_PreviewMouseLeftButtonDown;
            FoodListTreeView.PreviewMouseMove += List_MouseMove;

            FoodListTreeView.MouseDoubleClick += FoodListTreeView_MouseDoubleClick;
            FoodListTreeView.KeyDown += MainWindow_KeyDown;

            AddDayBtn.Click += AddDayBtn_Click;
            RemoveDayBtn.Click += RemoveDayBtn_Click;

            TheRightGroup.LoadDataEvent += TheRightGroup_LoadDataEvent;

            DaysContainer.Drop += newWd_Drop;
            DaysContainer.DragEnter += newWd_DragEnter;
        }

        private void MainWindow_Closing(object sender, CancelEventArgs e)
        {
            WarningPopUp wpp = new WarningPopUp();
            wpp.SetMessage = "Tem a certeza que deseja fechar a aplicação?";
            wpp.Title = "Aviso";
            wpp.Owner = Application.Current.MainWindow;

            wpp.ShowDialog();

            if (!wpp.PositiveSelection)
            {
                e.Cancel = true;
            }
        }
                
        /// <summary>
        /// Check if key is ENTER and selected item is a Food then clone it to the other list view
        /// </summary>
        /// <param name="sender">sender</param>
        /// <param name="e">KeyEventArgs</param>
        void MainWindow_KeyDown(object sender, KeyEventArgs e)
        {
            if (e != null)
            {
                if (e.Key == Key.Enter && FoodListTreeView.SelectedItem != null)
                {
                    FoodBase foodBase = ((FoodBase)FoodListTreeView.SelectedItem).Clone();
                    Food food = (foodBase as Food);
                    AddFoodToMeal(food);
                }
            }
        }

        /// <summary>
        /// Add food to Meals List with double mouse click
        /// </summary>
        /// <param name="sender">object</param>
        /// <param name="e">MouseButtonEventArgs</param>
        private void FoodListTreeView_MouseDoubleClick(object sender, MouseButtonEventArgs e)
        {
            if (e != null)
            {
                if (FoodListTreeView.SelectedItem != null && ((System.Windows.RoutedEventArgs)(e)).OriginalSource is TextBlock)
                {
                    FoodBase foodBase = ((FoodBase)FoodListTreeView.SelectedItem).Clone();

                    Food food = (foodBase as Food);
                    AddFoodToMeal(food);
                }
            }
        }

        /// <summary>
        /// Handle the Results load data event
        /// </summary>
        /// <param name="loaded"></param>
        private void TheRightGroup_LoadDataEvent(bool loaded)
        {
            bool b = TheRightGroup.PatientTabCtrl.HasChanges;

            if ((BackgroundInfo.Visibility == System.Windows.Visibility.Visible) != b)
            {
                ShowHideWeekDays = loaded;
            }

            TheRightGroup.ResultsTabCtrl.LoadElements(DaysContainer.Items.Count);
            CallCalculations();
        }

        /// <summary>
        /// Show hides week days elements
        /// </summary>
        private bool ShowHideWeekDays
        {
            set
            {
                BackgroundInfo.Visibility = (value) ? Visibility.Collapsed : Visibility.Visible;

                ExpandAllBtn.IsEnabled =
                    FoodListTreeView.IsEnabled =
                    SearchDPanel.IsEnabled = value;

                DaysContainer.Visibility = (value) ? Visibility.Visible : Visibility.Collapsed;

                if (value)
                {
                    if (DaysContainer.Items.Count < 1)
                    {
                        AddDayBtn_Click(null, null);
                    }
                }
            }
        }

        /// <summary>
        /// Check current save and load directories
        /// </summary>
        private void CheckDirectories()
        {
            SaveDirectory = "c:\\Program Files\\Alimentador\\";//System.AppDomain.CurrentDomain.BaseDirectory;
            ProfileDirectory = SaveDirectory + "Profiles\\";
            try
            {
                if (!System.IO.Directory.Exists(ProfileDirectory))
                {
                    System.IO.Directory.CreateDirectory(ProfileDirectory);
                }
            }
            catch (Exception)
            {
                // TODO error log
            }

            try
            {
                MenusDirectory = MainWindow.SaveDirectory + MENUS_FOLDER + CurrentPatient.PatName + "\\";
                if (!System.IO.Directory.Exists(MenusDirectory))
                {
                    System.IO.Directory.CreateDirectory(MenusDirectory);
                }
            }
            catch (Exception)
            {
                // TODO error log
            }

        }

        /// <summary>
        /// Getter for main food list object
        /// </summary>
        public List<MainCategoryList> MainFoodList
        {
            get
            {
                return m_mainFoodList;
            }
        }

        /// <summary>
        /// Load main food list to tree view. Returns boolean result
        /// </summary>
        /// <returns>bool</returns>
        private bool LoadFoodListToTreeView()
        {
            if (m_mainFoodList != null)
            {
                FoodListTreeView.ItemsSource = m_mainFoodList;
                return true;
            }
            return false;
        }

        /// <summary>
        /// Fill food list with values from files.
        /// </summary>
        private bool LoadFoodListFromFiles()
        {
            try
            {
                IEnumerable<string> dirList = System.IO.Directory.EnumerateDirectories(ALIMENTOS_PATH);
                foreach (string dir in dirList)
                {
                    MainCategoryList mList = LoadMainCategoryListDir(dir);
                    if (mList != null && !string.IsNullOrEmpty(mList.GetName))
                    {
                        m_mainFoodList.Add(mList);
                    }
                }

                if(m_mainFoodList.Count > 0)
                {
                    m_mainFoodList = MainHelper.CompareListAndReturnFinal(m_mainFoodList, LoadFoodListFromXML());
                    SaveListToXML();
                }

                m_mainFoodList = LoadFoodListFromXML();

                //remove all excel data
                ClearAttributes(ALIMENTOS_PATH);

                try
                {
                    if (Directory.Exists(ALIMENTOS_PATH))
                    {
                        foreach (string MainFolder in Directory.GetDirectories(ALIMENTOS_PATH))
                        {
                            if (Directory.Exists(MainFolder))
                            { 
                                foreach (string folder in Directory.GetDirectories(MainFolder))
                                {
                                    if(Directory.Exists(folder))
                                    {
                                        foreach (string file in Directory.GetFiles(folder))
                                        {
                                            File.Delete(file);
                                        }
                                        ClearAttributes(folder);
                                        Directory.Delete(folder, true);
                                    }
                                }
                                ClearAttributes(MainFolder);
                                Directory.Delete(MainFolder, true);
                            }
                        }
                    }
                }
                catch (Exception ex)
                {
                    return true;
                }

                return true;
            }
            catch (Exception)
            {
                return false;
            }
        }

        private void ClearAttributes(string currentDir)
        {
            if (Directory.Exists(currentDir))
            {
                string[] subDirs = Directory.GetDirectories(currentDir);
                foreach (string dir in subDirs)
                    ClearAttributes(dir);
                string[] files = files = Directory.GetFiles(currentDir);
                foreach (string file in files)
                    File.SetAttributes(file, FileAttributes.Normal);
            }
        }

        private bool SaveListToXML()
        {
            try
            {
                XmlSerializer mainListSerializer = new XmlSerializer(m_mainFoodList.GetType());
                StreamWriter sw = new StreamWriter(ALIMENTOS_PATH + "\\" + NEW_FOOD_XML_FILENAME);
                mainListSerializer.Serialize(sw, m_mainFoodList);
                sw.Close();

                return true;
            }
            catch (Exception)
            {
                return false;
            }
        }

        private List<MainCategoryList> LoadFoodListFromXML()
        {
            List<MainCategoryList> listFromFile = new List<MainCategoryList>();
            try
            {
                string path = ALIMENTOS_PATH + "\\" + NEW_FOOD_XML_FILENAME;
                listFromFile = new List<MainCategoryList>();
                XmlSerializer serializer = new XmlSerializer(m_mainFoodList.GetType());
                StreamReader reader = new StreamReader(path);
                listFromFile = (List<MainCategoryList>)serializer.Deserialize(reader);
                reader.Close();
            }
            catch
            {
            }
            return listFromFile;
        }

        /// <summary>
        /// Load category list values for given directory. Returns an empty list on error.
        /// </summary>
        /// <param name="currentDir">string</param>
        /// <returns>MainCategoryList</returns>
        private MainCategoryList LoadMainCategoryListDir(string currentDir)
        {
            MainCategoryList mainFoodList = new MainCategoryList();

            try
            {
                IEnumerable<string> dirList = System.IO.Directory.EnumerateDirectories(currentDir);

                if (dirList != null && dirList.ToList().Count > 0)
                {
                    mainFoodList.MainFoods = new ObservableCollection<FoodCategory>();
                    mainFoodList.GetName = currentDir.Substring(currentDir.LastIndexOf('\\') + 1, currentDir.Length - currentDir.LastIndexOf('\\') - 1);
                    mainFoodList.GetItemType = FoodBase.ItemType.Category;

                    foreach (string dir in dirList)
                    {
                        FoodCategory innerFoodList = LoadFoodListDir(dir);
                        if (innerFoodList != null && !string.IsNullOrEmpty(innerFoodList.GetName))
                        {
                            mainFoodList.MainFoods.Add(innerFoodList);
                        }
                    }
                }
            }
            catch (Exception)
            {
                // TODO log exception
            }

            return mainFoodList;
        }

        /// <summary>
        /// Load a FoodCategory for given directory. Returns an empty list on error.
        /// </summary>
        /// <param name="currentDir">string</param>
        /// <returns>FoodCategory</returns>
        private FoodCategory LoadFoodListDir(string currentDir)
        {
            FoodCategory foodList = new FoodCategory();

            try
            {
                foodList.GetName = currentDir.Substring(currentDir.LastIndexOf('\\') + 1, currentDir.Length - currentDir.LastIndexOf('\\') - 1);
                foodList.GetItemType = FoodBase.ItemType.Category;

                IEnumerable<string> dirFiles = System.IO.Directory.EnumerateFiles(currentDir);
                List<string> errorFiles = foodList.LoadFoodListFromFiles(dirFiles);

                if (errorFiles.Count > 0)
                {
                    string errors = "";
                    foreach (string s in errorFiles)
                    {
                        errors += "\n\t" + s;
                    }
                    MessageBox.Show("Estes ficheiros não foram carregados:" + errors, "Aviso", MessageBoxButton.OK, MessageBoxImage.Information);
                }
            }
            catch (Exception ex)
            {
                // TODO log exception error
                MessageBox.Show("Alguns ficheiros não carregados:" + ex.Message, "Aviso", MessageBoxButton.OK, MessageBoxImage.Information);
            }

            return foodList;
        }

        /// <summary>
        /// SearchTextBox text changed event to call for items refresh
        /// </summary>
        /// <param name="sender">object</param>
        /// <param name="e">TextChangedEventArgs</param>
        private void SearchTBox_TextChanged(object sender, TextChangedEventArgs e)
        {
            if (string.IsNullOrEmpty(SearchTBox.Text))
            {
                FoodListTreeView.ItemsSource = m_mainFoodList;
                CollectionViewSource.GetDefaultView(FoodListTreeView.ItemsSource).Refresh();
                return;
            }

            List<MainCategoryList> fullList = new List<MainCategoryList>();

            foreach (MainCategoryList mcl in m_mainFoodList)
            {
                bool hasFoundCategory = false;

                MainCategoryList mmcl = new MainCategoryList();
                mmcl.GetName = mcl.GetName;

                foreach (FoodCategory fc in mcl.MainFoods)
                {
                    bool hasFoundFood = false;
                    FoodCategory mfc = new FoodCategory();
                    mfc.GetName = fc.GetName;

                    foreach (Food food in fc.Foods)
                    {
                        if (food.GetName.ToLower().Contains(SearchTBox.Text.ToLower()))
                        {
                            mfc.Foods.Add(food);
                            hasFoundFood = true;
                        }
                    }

                    if (fc.GetName.ToLower().Contains(SearchTBox.Text.ToLower()) || hasFoundFood)
                    {
                        mmcl.MainFoods.Add(mfc);
                        hasFoundCategory = true;
                    }
                }

                if (mcl.GetName.ToLower().Contains(SearchTBox.Text.ToLower()) || hasFoundCategory)
                {
                    fullList.Add(mmcl);
                }
            }

            FoodListTreeView.ItemsSource = fullList;

            CollectionViewSource.GetDefaultView(FoodListTreeView.ItemsSource).Refresh();

            ExpandAllBtn.IsChecked = true;
            ExpandAllBtn_Click(null, null);
        }

        /// <summary>
        /// Expression for Tree view filter. Returns filter result
        /// </summary>
        /// <param name="item">object</param>
        /// <returns>bool</returns>
        private bool UserFilter(object item)
        {
            bool result = true;
            if (String.IsNullOrEmpty(SearchTBox.Text))
            {
                return result;
            }
            else
            {
                try
                {
                    FoodBase fb = (item as FoodBase);
                    if (fb != null)
                    {
                        string name = fb.GetName;
                        result = (name.IndexOf(SearchTBox.Text, StringComparison.OrdinalIgnoreCase) >= 0);
                    }
                }
                catch
                {
                    //TODO: Log Exception
                }
            }

            return result;
        }

        /// <summary>
        /// Fill tree view values
        /// </summary>
        private void SetTreeViewItems()
        {
            CollectionView view = (CollectionView)CollectionViewSource.GetDefaultView(FoodListTreeView.ItemsSource);
            if (view != null)
            {
                view.SortDescriptions.Add(new SortDescription("GetName", ListSortDirection.Ascending));
                view.Filter = UserFilter;

                PropertyGroupDescription groupDescription = new PropertyGroupDescription("GetName");
                if (view.GroupDescriptions != null && groupDescription != null)
                {
                    view.GroupDescriptions.Add(groupDescription);
                }
            }
        }

        /// <summary>
        /// Store the mouse position
        /// </summary>
        /// <param name="sender">object</param>
        /// <param name="e">MouseButtonEventArgs</param>
        private void List_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            m_startPoint = e.GetPosition(null);
        }

        /// <summary>
        /// Detect mouse movement
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void List_MouseMove(object sender, MouseEventArgs e)
        {
            if (e.LeftButton == MouseButtonState.Pressed && e.Device.Target is TextBlock)
            {
                TreeView treeView = sender as TreeView;
                System.Windows.Point mousePos = e.GetPosition(null);
                Vector diff = m_startPoint - mousePos;

                if ((Math.Abs(diff.X) > SystemParameters.MinimumHorizontalDragDistance || Math.Abs(diff.Y) > SystemParameters.MinimumVerticalDragDistance))
                {
                    if (FoodListTreeView.SelectedItem != null)
                    {
                        FoodBase foodBase = ((FoodBase)FoodListTreeView.SelectedItem).Clone();

                        DataObject dragData = new DataObject("FoodBase", foodBase);
                        DragDrop.DoDragDrop(FoodListTreeView, dragData, DragDropEffects.All);
                    }
                }
            }
        }

        /// <summary>
        /// DropList drag event
        /// </summary>
        /// <param name="sender">object</param>
        /// <param name="e">DragEventArgs</param>
        private void DropList_DragEnter(object sender, DragEventArgs e)
        {
            if (!e.Data.GetDataPresent("myFormat") || sender == e.Source)
            {
                e.Effects = DragDropEffects.Copy;
            }
        }

        /// <summary>
        /// DropList drop event
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void DropList_Drop(object sender, DragEventArgs e)
        {
            if (e.Data.GetDataPresent("myFormat"))
            {
                String contact = e.Data.GetData("myFormat") as String;
                ListView listView = sender as ListView;
                listView.Items.Add(contact);
            }
            e.Handled = true;
        }

        /// <summary>
        /// Remove the selected day from list
        /// </summary>
        /// <param name="sender">object</param>
        /// <param name="e">RoutedEventArgs</param>
        private void RemoveDayBtn_Click(object sender, RoutedEventArgs e)
        {
            if (DaysContainer.SelectedIndex != -1)
            {
                MessageBoxResult msbr = MessageBox.Show("Tem a certeza que deseja remover o dia que está selecionado?", "Aviso", MessageBoxButton.YesNo, MessageBoxImage.Warning);
                if (msbr == MessageBoxResult.Yes)
                {
                    ((WeekDay)DaysContainer.SelectedItem).RemoveMeal();

                    m_daysContainer_ItemsCollection.Remove((WeekDay)DaysContainer.SelectedItem);
                    UpdateDaysContainer();
                }

                if (DaysContainer.Items.Count == 0)
                {
                    WeekList_cb.SelectedIndex = 0;
                    AddDayBtn_Click(null, null);
                }
                DaysContainer.SelectedIndex = DaysContainer.Items.Count - 1;

                TheRightGroup.ResultsTabCtrl.LoadElements(DaysContainer.Items.Count);
                CallCalculations();
            }
        }

        private List<WeekDay> m_daysContainer_ItemsCollection = new List<WeekDay>();
        private string m_CurrentMenuFile = "";

        /// <summary>
        /// Add week day to list
        /// </summary>
        /// <param name="sender">object</param>
        /// <param name="e">RoutedEventArgs</param>
        private void AddDayBtn_Click(object sender, RoutedEventArgs e)
        {
            ComboBoxItem selectedItem = (ComboBoxItem)WeekList_cb.SelectedItem;

            if (selectedItem == null)
            {
                return;
            }

            foreach (WeekDay wd in DaysContainer.Items)
            {
                if ((string)selectedItem.Content == (string)wd.Header)
                {
                    return;
                }
            }

            WeekDay newWd = new WeekDay();
            newWd.Header = (string)selectedItem.Content;

            AddDay(newWd);
        }

        private void AddDay(WeekDay newWd)
        {
            newWd.FoodAddedEvent += newWd_FoodAddedEvent;
            newWd.FoodRemovedEvent += newWd_FoodRemovedEvent;

            newWd.MealQuantityChangeEvent += newWd_MealQuantityChangeEvent;

            m_daysContainer_ItemsCollection.Add(newWd);
            UpdateDaysContainer();
            DaysContainer.SelectedItem = newWd;

            if (WeekList_cb.SelectedIndex + 1 < WeekList_cb.Items.Count)
            {
                WeekList_cb.SelectedIndex = WeekList_cb.SelectedIndex + 1;
            }

            TheRightGroup.ResultsTabCtrl.LoadElements(m_daysContainer_ItemsCollection.Count);
            CallCalculations();
        }

        private void UpdateDaysContainer()
        {
            DaysContainer.ItemsSource = m_daysContainer_ItemsCollection;
            ICollectionView view = CollectionViewSource.GetDefaultView(DaysContainer.ItemsSource);
            view.Refresh();
        }

        void newWd_Drop(object sender, DragEventArgs e)
        {
            FoodListTreeView_MouseDoubleClick(null, null);
        }

        void newWd_DragEnter(object sender, DragEventArgs e)
        {
            if (!e.Data.GetDataPresent("FoodBase") || sender == e.Source)
            {
                e.Effects = DragDropEffects.None;
            }
        }

        //private void Grid_DragEnter(object sender, DragEventArgs e)
        //{
        //    if (!e.Data.GetDataPresent("FoodBase") || sender == e.Source)
        //    {
        //        e.Effects = DragDropEffects.None;
        //    }
        //}

        //private void Grid_Drop(object sender, DragEventArgs e)
        //{
        //    if (e.Data.GetDataPresent("FoodBase"))
        //    {
        //        FoodBase droppedFood = e.Data.GetData("FoodBase") as FoodBase;
        //        if (droppedFood.GetItemType == FoodBase.ItemType.Food)
        //        {
        //            AddFood((Food)droppedFood);
        //        }
        //    }
        //}

        /// <summary>
        /// Handle the Food quantity change
        /// </summary>
        /// <param name="foodUpdated">FoodBase</param>
        void newWd_MealQuantityChangeEvent()
        {
            CallCalculations();
        }

        /// <summary>
        /// Call for results and grapchics calculations
        /// </summary>
        private void CallCalculations()
        {
            TheRightGroup.AddFood(m_foodList, m_daysContainer_ItemsCollection.Count);
            ChartAllValues.AddFood(m_foodList, m_daysContainer_ItemsCollection.Count);
            ChartEnergyValues.AddFood(m_foodList, m_daysContainer_ItemsCollection.Count);
        }

        /// <summary>
        /// Handle the event for adding a FoodBase to a meal
        /// </summary>
        /// <param name="foodAdded">FoodBase</param>
        private void newWd_FoodAddedEvent(FoodBase foodAdded)
        {
            if (foodAdded is Food)
            {
                bool found_bool = false;
                foreach (FoodBase fb in m_foodList)
                {
                    if (fb.GetName == foodAdded.GetName)
                    {
                        ((Food)fb).Quantity += ((Food)foodAdded).Quantity;
                        found_bool = true;
                        break;
                    }
                }

                if (!found_bool)
                {
                    Food fd = (Food)foodAdded;
                    m_foodList.Add(fd);
                }
            }

            CallCalculations();
        }

        /// <summary>
        /// Handle the event for removing a FoodBase from a meal
        /// </summary>
        /// <param name="foodRemoved"></param>
        private void newWd_FoodRemovedEvent(FoodBase foodRemoved)
        {
            if (foodRemoved is Food)
            {
                foreach (Food fd_lst in m_foodList)
                {
                    if (fd_lst.GetName == foodRemoved.GetName)
                    {
                        if (((Food)foodRemoved).Quantity < fd_lst.Quantity)
                        {
                            fd_lst.Quantity -= ((Food)foodRemoved).Quantity;
                        }
                        else
                        {
                            m_foodList.Remove(fd_lst);
                        }
                        break;
                    }

                }
            }

            CallCalculations();
        }

        /// <summary>
        /// Handles the Expand / Collapse button click.
        /// </summary>
        /// <param name="sender">object</param>
        /// <param name="e">RoutedEventArgs</param>
        private void ExpandAllBtn_Click(object sender, RoutedEventArgs e)
        {
            FoodListTreeView.Resources.Remove(typeof(TreeViewItem));
            if ((bool)ExpandAllBtn.IsChecked)
            {
                FoodListTreeView.Resources.Add(typeof(TreeViewItem), this.Resources["ExpandTreeStyle"]);
                ExpandAllBtn.Style = (Style)Application.Current.Resources["CollapseBtnStyle"];
                ExpandAllBtn.Content = "Fechar tudo";
            }
            else
            {
                //FoodListTreeView.Resources.Add(typeof(TreeViewItem), this.Resources["CollapseTreeStyle"]);
                ExpandAllBtn.Style = (Style)Application.Current.Resources["ExpandBtnStyle"];
                ExpandAllBtn.Content = "Expandir tudo";
                FoodListTreeView.ItemsSource = null;
                LoadFoodListToTreeView();
            }
        }

        /// <summary>
        /// Adds a given food to a meal component
        /// </summary>
        /// <param name="food">Food</param>
        private void AddFoodToMeal(Food food)
        {
            if (food != null && DaysContainer.SelectedIndex != -1)
            {
                WeekDay wd = (WeekDay)(DaysContainer.SelectedItem);
                if (wd != null && wd.MealsListView != null)
                {
                    if (wd.MealsListView.SelectedItem != null && wd.MealsListView.SelectedItem as MealCtrl != null)
                    {
                        (wd.MealsListView.SelectedItem as MealCtrl).AddFood(food);
                    }
                    else if (wd.MealsListView.Items.Count > 0)
                    {
                        (wd.MealsListView.Items[0] as MealCtrl).AddFood(food);
                        wd.MealsListView.SelectedItem = wd.MealsListView.Items[0];
                    }
                }
            }
        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            MainHelper.OnPrint(FoodListTreeView);
        }

        private void FoodDetailLeftBtn_Click(object sender, RoutedEventArgs e)
        {
            if (FoodListTreeView.SelectedItem != null && FoodListTreeView.SelectedItem is Food)
            {
                Food food = (Food)FoodListTreeView.SelectedItem;
                if (food != null)
                {
                    FoodListingPopup foodPopup = new FoodListingPopup();
                    foodPopup.FillListView(food);
                    foodPopup.Owner = Application.Current.MainWindow;
                    foodPopup.ShowDialog();
                }
            }
        }

        private void FoodDetailBtn_Click(object sender, RoutedEventArgs e)
        {
            if (DaysContainer.SelectedIndex != -1)
            {
                WeekDay wd = (WeekDay)(DaysContainer.SelectedItem);
                if (wd != null && wd.MealsListView != null)
                {
                    if (wd.MealsListView.SelectedItem != null && wd.MealsListView.SelectedItem as MealCtrl != null)
                    {
                        Food food = (wd.MealsListView.SelectedItem as MealCtrl).GetSelectedItem();

                        if (food != null)
                        {
                            FoodListingPopup foodPopup = new FoodListingPopup();
                            foodPopup.FillListView(food);
                            foodPopup.Owner = Application.Current.MainWindow;
                            foodPopup.ShowDialog();
                        }
                    }
                }
            }
        }

        private void HelpBtn_Click(object sender, RoutedEventArgs e)
        {
            string helpFileName = System.AppDomain.CurrentDomain.BaseDirectory + "\\Manual.pdf";

            System.Diagnostics.Process.Start(helpFileName);
        }

        private void OpenBtn_Click(object sender, RoutedEventArgs e)
        {
            CheckDirectories();
            LoadLocalFileListPopUp lplpu = new LoadLocalFileListPopUp(MenusDirectory, MENU_DATA_FILE_EXTENSION, PrintFromFile_click);
            lplpu.SetInstructions("Escolha o menu da lista abaixo:");
            lplpu.Owner = Application.Current.MainWindow;
            lplpu.ShowDialog();
            string CurrentMenuFile = lplpu.getSelectedItem();

            if (!string.IsNullOrEmpty(CurrentMenuFile))
            {
                try
                {
                    m_foodList = new List<FoodBase>();
                    m_daysContainer_ItemsCollection = new List<WeekDay>();
                    UpdateDaysContainer();

                    TheRightGroup.ResultsTabCtrl.LoadElements(DaysContainer.Items.Count);

                    m_foodList = PopulateScreenFromFile(MainHelper.DescSerializeDaysContainerObject(MenusDirectory + CurrentMenuFile + MENU_DATA_FILE_EXTENSION));

                    m_CurrentMenuFile = CurrentMenuFile;
                    AppTitle_tb.Text = AppName + ": " + CurrentMenuFile.ToLower();

                    CallCalculations();
                }
                catch (Exception)
                {
                    MessageBox.Show("Não foi possível carregar os dados.", "Aviso", MessageBoxButton.OK, MessageBoxImage.Warning);
                }
            }

        }

        private List<FoodBase> PopulateScreenFromFile(Week week)
        {
            List<FoodBase> foodListToReturn = new List<FoodBase>();
            foreach (Day d in week.DayList)
            {
                WeekDay newWd = new WeekDay();
                newWd.Header = d.DayName;

                foreach (Meal m in d.MealList)
                {
                    MealCtrl mc = newWd.AddMealCtrl_AddMealEvent(m.MealDescription);

                    foreach (FoodEssencial fe in m.FoodList)
                    {
                        foreach (MainCategoryList mcl in MainFoodList)
                        {
                            foreach (FoodCategory fc in mcl.MainFoods)
                            {
                                foreach (Food fd in fc.Foods)
                                {
                                    if (fd.GetName == fe.Name)
                                    {
                                        Food newFoodToAdd = (Food)fd.Clone();
                                        newFoodToAdd.GetQuantity = fe.Quantity;
                                        mc.AddFood(newFoodToAdd);
                                        foodListToReturn.Add(newFoodToAdd);
                                    }
                                }
                            }
                        }
                    }
                }

                AddDay(newWd);
            }

            return foodListToReturn;
        }

        /// <summary>
        /// Save food list menu
        /// </summary>
        /// <param name="sender">object</param>
        /// <param name="e">RoutedEventArgs</param>
        private void SaveBtn_Click(object sender, RoutedEventArgs e)
        {
            CheckDirectories();
            SaveMenuPopup smp = new SaveMenuPopup(m_CurrentMenuFile);
            smp.Owner = Application.Current.MainWindow;
            smp.ShowDialog();

            string fileName = smp.getFileName;
            if (!string.IsNullOrEmpty(fileName) && !string.IsNullOrWhiteSpace(fileName))
            {
                string regex = @"^[\w\-. ]+$";
                MatchCollection matches = Regex.Matches(fileName, regex);
                if (matches.Count > 0)
                {
                    string filePathAndName = MenusDirectory + fileName + MENU_DATA_FILE_EXTENSION;

                    if (File.Exists(filePathAndName))
                    {
                        MessageBoxResult mbr = MessageBox.Show("Este ficheiro já existe, deseja substituir?", "Aviso", MessageBoxButton.YesNo);
                        if (mbr == MessageBoxResult.Yes)
                        {
                            Save(filePathAndName, fileName);
                        }
                        else
                        {
                            SaveBtn_Click(sender, e);
                        }
                    }
                    else
                    {
                        Save(filePathAndName, fileName);
                    }
                }
                else
                {
                    MessageBox.Show("Nome de ficheiro inválido. Por favor use outro nome.", "Aviso", MessageBoxButton.OK);
                    SaveBtn_Click(sender, e);
                }
            }
        }

        private void Save(string filePathAndName, string fileName)
        {
            MainHelper.SerializeDaysContainerObject(filePathAndName, DaysContainer.Items);
            MessageBoxResult msbr = MessageBox.Show("Menu gravado com sucesso com o nome de: " + fileName, "Informação", MessageBoxButton.OK, MessageBoxImage.Information);
        }

        private void PrintBtn_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                PDFHelper.PDFHelper.SavePlan(CurrentPatient, DaysContainer.Items);//List<WeekDay>
            }
            catch (Exception)
            {
                MessageBox.Show("Erro ao tentar criar o ficheiro", "Aviso");
            }
        }

        private void PrintFromFile_click(string CurrentMenuFile)
        {
            CheckDirectories();
            Week wk = MainHelper.DescSerializeDaysContainerObject(MenusDirectory + CurrentMenuFile + MENU_DATA_FILE_EXTENSION);

            PDFHelper.PDFHelper.SavePlan(CurrentPatient, wk);
        }

        private void AddNewFoodBtn_Click(object sender, RoutedEventArgs e)
        {
            if (DaysContainer.SelectedIndex != -1)
            {
                WeekDay wd = (WeekDay)(DaysContainer.SelectedItem);
                if (wd != null && wd.MealsListView != null)
                {
                    if (wd.MealsListView.SelectedItem != null && wd.MealsListView.SelectedItem as MealCtrl != null)
                    {
                        bool error = false;

                        // Perguntar nome da comida - Validar os valores das somas
                        SaveMenuPopup smp = new SaveMenuPopup("");
                        smp.Owner = Application.Current.MainWindow;
                        smp.SetMenuName = "Escolha um nome para dar ao seu Alimento:";
                        smp.ShowDialog();
                        string foodName = smp.getFileName;
                        if (!string.IsNullOrEmpty(foodName) && !string.IsNullOrWhiteSpace(foodName))
                        {
                            Food newFood = new Food();
                            newFood.PropertyList = new List<FoodProperty>();
                            newFood.GetName = foodName;
                            newFood.GetItemType = FoodBase.ItemType.Food;
                            newFood.GetUnit = "g";

                            // Ficha ?!?
                            // Validar se já existe alimento com este nome
                            // colocar na main category list o metodo de procura
                            newFood.PropertyList.Add(new FoodProperty(PropertyName.Percentagem, 100));

                            foreach (FoodBase f in (wd.MealsListView.SelectedItem as MealCtrl).GetFoodList)
                            {
                                Food food = (Food)f;

                                foreach (FoodProperty p in food.PropertyList)
                                {
                                    if (p.PropertyName == PropertyName.Ficha || p.PropertyName == PropertyName.Percentagem)
                                    {
                                        continue;
                                    }

                                    FoodProperty fp = newFood.FindPropertyByName(p.PropertyName.ToString());

                                    if (fp != null)
                                    {
                                        newFood.FindPropertyByName(p.PropertyName.ToString()).Quantity += food.FindPropertyByName(p.PropertyName.ToString()).Quantity;
                                    }
                                    else
                                    {
                                        FoodProperty newFp = food.FindPropertyByName(p.PropertyName.ToString());
                                        if (newFp != null)
                                        {
                                            fp = new FoodProperty(p.PropertyName, newFp.Quantity);
                                        }
                                        else
                                        {
                                            fp = new FoodProperty(p.PropertyName, 0);
                                        }
                                        newFood.PropertyList.Add(fp);
                                    }
                                }
                            }

                            FoodCategory fcat = null;
                            MainCategoryList mainOutros = null;

                            foreach (MainCategoryList m in m_mainFoodList)
                            {
                                if (m.GetName == MainHelper.MAIN_CATEGORY_LIST_MEUS_ALIMENTOS)
                                {
                                    mainOutros = m;
                                    foreach (FoodCategory fg in m.MainFoods)
                                    {

                                        if (fg.GetName == MainHelper.FOOD_CATEGORY_ALIMENTOS)
                                        {
                                            fcat = fg;
                                            fg.Foods.Add(newFood);
                                            break;
                                        }
                                    }

                                    // Not found create
                                    if (fcat == null)
                                    {
                                        fcat = new FoodCategory();
                                        fcat.GetName = MainHelper.FOOD_CATEGORY_ALIMENTOS;
                                        fcat.Foods.Add(newFood);
                                        break;
                                    }
                                }
                            }

                            if (mainOutros == null)
                            {
                                mainOutros = new MainCategoryList();
                                mainOutros.GetName = MainHelper.MAIN_CATEGORY_LIST_MEUS_ALIMENTOS;

                                fcat = new FoodCategory();
                                fcat.GetName = MainHelper.FOOD_CATEGORY_ALIMENTOS;
                                fcat.Foods.Add(newFood);

                                mainOutros.MainFoods.Add(fcat);
                                m_mainFoodList.Add(mainOutros);
                            }
                        }
                        else
                        {
                            error = true;
                        }

                        if (SearchTBox != null)
                        {
                            SearchTBox.Text = "";
                        }

                        // Gravar XML
                        error = SaveListToXML() && error;
                        if (!error)
                        {
                            LoadFoodListToTreeView();
                            SetTreeViewItems();
                        }

                        if (error)
                        {
                            MessageBoxResult msbr = MessageBox.Show("Não foi possível gravar o seu alimento.", "Informação", MessageBoxButton.OK, MessageBoxImage.Information);
                        }
                    }
                }
            }
        }
    }
}